import * as utils from '../utils'

/**
 * 合并两个配置，返回一个新的配置
 * @param config1 配置1
 * @param config2 配置2
 */
export default function mergeConfig(config1: any, config2: any = {}) {
    let config = {};
    let valueFromConfig2Keys = ['url', 'method', 'data'];
    let mergeDeepPropertiesKeys = ['headers', 'auth', 'proxy', 'params'];
    let defaultToConfig2Keys = [
        'baseURL', 'transformRequest', 'transformResponse', 'paramsSerializer',
        'timeout', 'timeoutMessage', 'withCredentials', 'adapter', 'responseType', 'xsrfCookieName',
        'xsrfHeaderName', 'onUploadProgress', 'onDownloadProgress', 'decompress',
        'maxContentLength', 'maxBodyLength', 'maxRedirects', 'transport', 'httpAgent',
        'httpsAgent', 'cancelToken', 'socketPath', 'responseEncoding'
    ];
    let directMergeKeys = ['validateStatus'];

    function mergeDeepProperties(prop) {
        if (!utils.isUndefined(config2[prop])) {
            config[prop] = getMergedValue(config1[prop], config2[prop]);
        } else if (!utils.isUndefined(config1[prop])) {
            config[prop] = getMergedValue(undefined, config1[prop]);
        }
    }
    utils.forEach(valueFromConfig2Keys, function valueFromConfig2(prop) {
        if (!utils.isUndefined(config2[prop])) {
            config[prop] = getMergedValue(undefined, config2[prop]);
        }
    });

    utils.forEach(mergeDeepPropertiesKeys, mergeDeepProperties);

    utils.forEach(defaultToConfig2Keys, function defaultToConfig2(prop) {
        if (!utils.isUndefined(config2[prop])) {
            config[prop] = getMergedValue(undefined, config2[prop]);
        } else if (!utils.isUndefined(config1[prop])) {
            config[prop] = getMergedValue(undefined, config1[prop]);
        }
    });

    utils.forEach(directMergeKeys, function merge(prop) {
        if (prop in config2) {
            config[prop] = getMergedValue(config1[prop], config2[prop]);
        } else if (prop in config1) {
            config[prop] = getMergedValue(undefined, config1[prop]);
        }
    });

    var axiosKeys = valueFromConfig2Keys
        .concat(mergeDeepPropertiesKeys)
        .concat(defaultToConfig2Keys)
        .concat(directMergeKeys);

    var otherKeys = Object
        .keys(config1)
        .concat(Object.keys(config2))
        .filter(function filterAxiosKeys(key) {
            return axiosKeys.indexOf(key) === -1;
        });

    utils.forEach(otherKeys, mergeDeepProperties);

    return config;
}

function getMergedValue(target, source) {
    if (utils.isPlainObject(target) && utils.isPlainObject(source)) {
        return utils.merge(target, source);
    } else if (utils.isPlainObject(source)) {
        return utils.merge({}, source);
    } else if (utils.isArray(source)) {
        return source.slice();
    }
    return source;
}
